﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CADTool.Jig
{
    public class TriangleCircleJig : EntityJig
    {
        //声明类的成员变量
        private Point3d m_CenterPt; //等边三角形的中心点（UCS点）
        private Point3d m_peakPt;   //拖拽时的鼠标位置
        private Point2d[] m_pts=new Point2d[3];    //等边三角形顶点UCS坐标数组
        private Matrix3d m_mt = Matrix3d.Identity; //变换矩阵
        public ObjectId m_CirId = ObjectId.Null; //内切圆的ObjectId
        //派生类的构造函数
        public TriangleCircleJig(Point3d cenPt, ObjectId cirId) : base(new Polyline())
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            m_mt = ed.CurrentUserCoordinateSystem;
            //初始化等边三角形
            ((Polyline)Entity).AddVertexAt(0, Point2d.Origin, 0.0, 0.0, 0.0);
            ((Polyline)Entity).AddVertexAt(0, Point2d.Origin, 0.0, 0.0, 0.0);
            ((Polyline)Entity).AddVertexAt(0, Point2d.Origin, 0.0, 0.0, 0.0);
            //传递参数
            m_CenterPt = cenPt;
            m_CirId = cirId;
        }   
        //用于得到派生类图形对象
        public Entity GetEntity()
        {
            return Entity;
        }
        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            //定义一个点拖拽交互类
            JigPromptPointOptions optJig = new JigPromptPointOptions("\n请指定等边三角形的一个顶点");
            //光标类型
            optJig.Cursor = CursorType.RubberBand;
            //拖拽限制
            optJig.UserInputControls = UserInputControls.Accept3dCoordinates;
            //拖拽基点必须是WCS点
            optJig.BasePoint = m_CenterPt.TransformBy(m_mt);
            optJig.UseBasePoint = true;
            //用AcquirePoint函数得到用户拖拽鼠标的位置（WCS点）
            PromptPointResult resJig = prompts.AcquirePoint(optJig);
            Point3d curPt = resJig.Value;
            //拖拽取消
            if (resJig.Status == PromptStatus.Cancel)
            {
                return SamplerStatus.NoChange;
            }
            //拖拽
            if (m_peakPt != curPt)
            {
                //保存当前点
                m_peakPt = curPt;
                //等边三角形的中心
                Point2d cenPt = new Point2d(m_CenterPt.X, m_CenterPt.Y);
                //计算三角形的第一个顶点
                m_pts[0] = new Point2d(m_peakPt.TransformBy(m_mt.Inverse()).X, m_peakPt.TransformBy(m_mt.Inverse()).Y); //转换为UCS点
                //计算等边三角形另外2个顶点的UCS坐标
                double dis = m_pts[0].GetDistanceTo(cenPt);
                Vector2d vec = m_pts[0] - cenPt;
                double ang = vec.Angle;
                m_pts[1] = PolarPoint(cenPt, ang + Rad2Ang(120.0), dis);
                m_pts[2] = PolarPoint(cenPt, ang + Rad2Ang(240.0), dis);
                return SamplerStatus.OK;
            }
            else 
            { 
                //拖拽暂停
                return SamplerStatus.NoChange;
            }
        }
        protected override bool Update()
        {
            Database db = HostApplicationServices.WorkingDatabase;
            //更新等边三角形各个顶点的坐标
            ((Polyline)Entity).SetPointAt(0, m_pts[0]);
            ((Polyline)Entity).SetPointAt(1, m_pts[1]);
            ((Polyline)Entity).SetPointAt(2, m_pts[2]);           
            //对等边三角形进行矩阵变换，必须重新设定其法向矢量和标高
            ((Polyline)Entity).Normal = Vector3d.ZAxis;
            ((Polyline)Entity).Elevation = 0.0;
            ((Polyline)Entity).TransformBy(m_mt);
            //用事务打开要拽的圆，更新其参数
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                Circle circle = trans.GetObject(m_CirId, OpenMode.ForWrite) as Circle;
                circle.Center = m_CenterPt.TransformBy(m_mt);
                circle.Normal = m_mt.CoordinateSystem3d.Zaxis;
                double radius = 0.5 * m_pts[0].GetDistanceTo(m_pts[1]) * Math.Tan(Rad2Ang(30.0));
                if (radius > 0.0)
                {
                    circle.Radius = radius;
                }
                trans.Commit();
            }
            return true;
        }
        /// <summary>
        /// 获取与给定点指定角度和距离的点
        /// </summary>
        /// <param name="basePt">基点</param>
        /// <param name="angle">角度</param>
        /// <param name="dist">距离</param>
        /// <returns>Point2d</returns>
        public static Point2d PolarPoint( Point2d basePt, double angle, double dist)
        {
            double x = basePt[0] + dist * Math.Cos(angle);
            double y = basePt[1] + dist * Math.Sin(angle);
            return new Point2d(x, y);
        }
        /// <summary>
        /// 角度转弧度
        /// </summary>
        /// <param name="angle">角度</param>
        /// <returns>弧度</returns>
        public double Rad2Ang(double angle)
        {
            return angle * Math.PI / 180.0;
        }
    }
}
